home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / General / DR1.#1 PowerPlant ƒ / LPane.cp < prev    next >
Text File  |  1994-02-10  |  31KB  |  1,379 lines

  1. // ===========================================================================
  2. //    LPane.cp                        ©1993 Metrowerks Inc. All rights reserved.
  3. // ===========================================================================
  4. //
  5. //    Abstract class for an object that can draw itself and respond to
  6. //    mouse clicks
  7.  
  8. #include "LPane.h"
  9. #include "LView.h"
  10. #include "LStream.h"
  11.  
  12.  
  13. const Int16        multiClick_Distance = 4;
  14.  
  15.  
  16. // === Static Members ===
  17.  
  18. LView*    LPane::sDefaultView = nil;        // Default SuperView for new Panes
  19. LPane*    LPane::sLastPaneClicked = nil;    // Pane hit by last mouse click
  20. Uint32    LPane::sWhenLastMouseUp = 0;
  21. Uint32    LPane::sWhenLastMouseDown = 0;
  22. Point    LPane::sWhereLastMouseDown;
  23. Int16    LPane::sClickCount = 0;
  24.  
  25.  
  26. // ---------------------------------------------------------------------------
  27. //        • LPane()
  28. // ---------------------------------------------------------------------------
  29. //    Default Constructor
  30.  
  31. LPane::LPane()
  32. {
  33.     mPaneID = 0;
  34.     mFrameSize.width = mFrameSize.height = 0;
  35.     mFrameLocation.h = mFrameLocation.v = 0;
  36.     mRefCon = 0;
  37.     
  38.     mFrameBinding.left =
  39.         mFrameBinding.top =
  40.         mFrameBinding.right =
  41.         mFrameBinding.bottom = false;
  42.  
  43.     mSuperView = nil;
  44.     
  45.     mVisible = mActive = mEnabled = triState_Latent;
  46.     mLockLevel = 0;
  47. }
  48.  
  49.  
  50. // ---------------------------------------------------------------------------
  51. //        • LPane(const LPane&)
  52. // ---------------------------------------------------------------------------
  53. //    Copy Constructor
  54.  
  55. LPane::LPane(
  56.     const LPane    &inOriginal)
  57. {
  58.                                     // Copy members of Original
  59.     mPaneID = inOriginal.mPaneID;
  60.     mFrameSize = inOriginal.mFrameSize;
  61.     mFrameLocation = inOriginal.mFrameLocation;
  62.     mFrameBinding = inOriginal.mFrameBinding;
  63.     mRefCon = inOriginal.mRefCon;
  64.     
  65.     mSuperView = nil;                // Copy is not inside any View
  66.     
  67.                                     // Pane properties. If Original has
  68.                                     //   property ON, Copy is Latent.
  69.     mVisible = inOriginal.mVisible;
  70.     if (mVisible == triState_On) {
  71.         mVisible = triState_Latent;
  72.     }
  73.  
  74.     mActive = inOriginal.mActive;
  75.     if (mActive == triState_On) {
  76.         mActive = triState_Latent;
  77.     }
  78.  
  79.     mEnabled = inOriginal.mEnabled;
  80.     if (mEnabled == triState_On) {
  81.         mEnabled = triState_Latent;
  82.     }
  83.  
  84.     mLockLevel = 0;
  85. }
  86.  
  87.  
  88. // ---------------------------------------------------------------------------
  89. //        • LPane(LStream*)
  90. // ---------------------------------------------------------------------------
  91. //    Construct Pane from data in a Stream
  92.  
  93. LPane::LPane(
  94.     LStream    *inStream)
  95. {
  96.     DataIDT        dataID;
  97.     inStream->ReadData(&dataID, sizeof(DataIDT));
  98.     SignalIf_(dataID != 'Pane');
  99.  
  100.     SPaneInfo    paneInfo;
  101.     inStream->ReadData(&paneInfo, sizeof(SPaneInfo));
  102.     
  103.     mPaneID = paneInfo.paneID;
  104.     mFrameSize.width = paneInfo.width;
  105.     mFrameSize.height = paneInfo.height;
  106.     mRefCon = paneInfo.refCon;
  107.     
  108.     mVisible = triState_Off;
  109.     if (paneInfo.visible) {
  110.         mVisible = triState_Latent;
  111.     }
  112.  
  113.     mActive = triState_Latent;
  114.  
  115.     mEnabled = triState_Off;
  116.     if (paneInfo.enabled) {
  117.         mEnabled = triState_Latent;
  118.     }
  119.     
  120.     mFrameBinding = paneInfo.bindings;
  121.     mLockLevel = 0;
  122.     
  123.     mSuperView = nil;
  124.     PutInside(GetDefaultView());
  125.     if (mSuperView != nil) {
  126.         PlaceInSuperImageAt(paneInfo.leftInSuperImage,
  127.                             paneInfo.topInSuperImage, false);
  128.     }
  129. }
  130.  
  131.  
  132. // ---------------------------------------------------------------------------
  133. //        • ~LPane
  134. // ---------------------------------------------------------------------------
  135. //    Destructor
  136.  
  137. LPane::~LPane()
  138. {
  139.     PutInside(nil);
  140.     
  141.     if (sLastPaneClicked == this) {
  142.         sLastPaneClicked = nil;
  143.     }
  144. }
  145.  
  146.  
  147. // ---------------------------------------------------------------------------
  148. //        • FinishCreate
  149. // ---------------------------------------------------------------------------
  150. //    Wrapper function for FinishCreateSelf
  151. //    You will rarely want to override this function
  152.  
  153. void
  154. LPane::FinishCreate()
  155. {
  156.     FinishCreateSelf();
  157. }
  158.  
  159.  
  160. // ---------------------------------------------------------------------------
  161. //        • FinishCreateSelf
  162. // ---------------------------------------------------------------------------
  163. //    Finish Creating a Pane
  164. //
  165. //    This function gets called after creating a Pane from a data stream.
  166. //    Override to perform finishing touches that depend on the entire
  167. //    Pane hierarchy being constructed.
  168. //
  169. //    For example, if a View wants to store a pointer to a SubPane,
  170. //    it should override this function to call FindPaneByID for that
  171. //    Pane. This saves the overhead of repeatedly calling FindPaneByID
  172. //    when the View wants to access that SubPane. You can't do this from
  173. //    a Constructor because SubPanes are created after their SuperView.
  174.  
  175. void
  176. LPane::FinishCreateSelf()
  177. {
  178. }
  179.  
  180.  
  181. Boolean
  182. LPane::IsAreaInQDSpace(
  183.     Int32    inLeft,
  184.     Int32    inTop,
  185.     Int16    inWidth,
  186.     Int16    inHeight)
  187. {
  188.     return ( (inLeft > min_QDCoord)  &&
  189.              (inTop > min_QDCoord)  &&
  190.              (inLeft + inWidth < max_QDCoord)  &&
  191.              (inTop + inHeight < max_QDCoord) );
  192. }
  193.  
  194.  
  195. PaneIDT
  196. LPane::GetPaneID() const
  197. {
  198.     return mPaneID;
  199. }
  200.  
  201.  
  202. void
  203. LPane::SetPaneID(
  204.     PaneIDT    inPaneID)
  205. {
  206.     mPaneID = inPaneID;
  207. }
  208.  
  209.  
  210. LPane*
  211. LPane::FindPaneByID(
  212.     PaneIDT    inPaneID)
  213. {
  214.     return (inPaneID == mPaneID) ? this : nil;
  215. }
  216.  
  217.  
  218. LView*
  219. LPane::GetDefaultView()
  220. {
  221.     return sDefaultView;
  222. }
  223.  
  224.  
  225. void
  226. LPane::SetDefaultView(
  227.     LView    *inView)
  228. {
  229.     sDefaultView = inView;
  230. }
  231.  
  232.  
  233. GrafPtr
  234. LPane::GetMacPort() const
  235. {
  236.     return (mSuperView == nil) ? nil : mSuperView->GetMacPort();
  237. }
  238.  
  239.  
  240. Int32
  241. LPane::GetValue() const
  242. {
  243.     BreakIfDebug_("GetValue undefined");
  244.     return 0;
  245. }
  246.  
  247.  
  248. void
  249. LPane::SetValue(
  250.     Int32    inValue)
  251. {
  252.     BreakIfDebug_("SetValue undefined");
  253. }
  254.  
  255.  
  256. StringPtr
  257. LPane::GetDescriptor(
  258.     Str255    outDescriptor) const
  259. {
  260.     BreakIfDebug_("GetDescriptor undefined");
  261.     outDescriptor[0] = 0;
  262.     return outDescriptor;
  263. }
  264.  
  265.  
  266. void
  267. LPane::SetDescriptor(
  268.     ConstStr255Param    inDescriptor)
  269. {
  270.     BreakIfDebug_("SetDescriptor undefined");
  271. }
  272.  
  273.  
  274. Int32
  275. LPane::GetRefCon() const
  276. {
  277.     return mRefCon;
  278. }
  279.  
  280.  
  281. void
  282. LPane::SetRefCon(
  283.     Int32    inRefCon)
  284. {
  285.     mRefCon = inRefCon;
  286. }
  287.  
  288.  
  289. void
  290. LPane::GetFrameSize(
  291.     SDimension16    &outSize) const
  292. {
  293.     outSize = mFrameSize;
  294. }
  295.  
  296.  
  297. void
  298. LPane::GetFrameLocation(
  299.     SPoint32    &outLocation) const
  300. {
  301.     outLocation = mFrameLocation;
  302. }
  303.  
  304.  
  305. void
  306. LPane::SetFrameBinding(
  307.     const SBooleanRect    &inFrameBinding)
  308. {
  309.     mFrameBinding = inFrameBinding;
  310. }
  311.  
  312.  
  313. // ---------------------------------------------------------------------------
  314. //        • CalcPortFrameRect
  315. // ---------------------------------------------------------------------------
  316. //    Calculate the Pane's Frame Rectangle in Port coordinates
  317. //
  318. //    Returns true if the Frame is within QuickDraw space (16-bit)
  319. //    Returns false if the Frame is outside QuickDraw space
  320. //        and outRect is unchanged
  321.  
  322. Boolean
  323. LPane::CalcPortFrameRect(
  324.     Rect    &outRect) const
  325. {
  326.     Boolean        isInQDSpace =
  327.                 IsAreaInQDSpace(mFrameLocation.h, mFrameLocation.v,
  328.                                 mFrameSize.width, mFrameSize.height);
  329.     if (isInQDSpace) {
  330.         outRect.left = mFrameLocation.h;
  331.         outRect.top = mFrameLocation.v;
  332.         outRect.right = outRect.left + mFrameSize.width;
  333.         outRect.bottom = outRect.top + mFrameSize.height;
  334.     }
  335.     return isInQDSpace;
  336. }
  337.  
  338.  
  339. // ---------------------------------------------------------------------------
  340. //        • CalcLocalFrameRect
  341. // ---------------------------------------------------------------------------
  342. //    Calculate the Pane's Frame Rectangle in local (Image) coordinates
  343. //
  344. //    Returns true if the Frame is within QuickDraw space (16-bit)
  345. //    Returns false if the Frame is outside QuickDraw space
  346. //        and outRect is unchanged
  347.  
  348. Boolean
  349. LPane::CalcLocalFrameRect(
  350.     Rect    &outRect) const
  351. {
  352.     Boolean        isInQDSpace = CalcPortFrameRect(outRect);
  353.     if (isInQDSpace) {
  354.         PortToLocalPoint(topLeft(outRect));
  355.         PortToLocalPoint(botRight(outRect));
  356.     }
  357.     return isInQDSpace;
  358. }
  359.  
  360.  
  361. RgnHandle
  362. LPane::GetLocalUpdateRgn()
  363. {
  364.     RgnHandle    localUpdateRgnH = nil;
  365.  
  366.     if (mSuperView != nil) {
  367.         localUpdateRgnH = mSuperView->GetLocalUpdateRgn();
  368.     }
  369.     
  370.     return localUpdateRgnH;
  371. }
  372.  
  373.  
  374. // ---------------------------------------------------------------------------
  375. //        • ResizeFrameTo
  376. // ---------------------------------------------------------------------------
  377. //    Set the dimensions of the Frame
  378. //
  379. //        inWidth and inHeight specify the new size in pixels
  380.  
  381. void
  382. LPane::ResizeFrameTo(
  383.     Int16        inWidth,
  384.     Int16        inHeight,
  385.     Boolean        inRefresh)
  386. {
  387.     ResizeFrameBy(inWidth - mFrameSize.width,
  388.                   inHeight - mFrameSize.height,
  389.                   inRefresh);
  390. }
  391.  
  392.  
  393. // ---------------------------------------------------------------------------
  394. //        • ResizeFrameBy
  395. // ---------------------------------------------------------------------------
  396. //    Change the Frame size by the specified amounts
  397. //
  398. //        inWidthDelta and inHeightDelta specify, in pixels, how much larger
  399. //        to make the Frame. Positive deltas increase the size, negative deltas
  400. //        reduce the size.
  401.  
  402. void
  403. LPane::ResizeFrameBy(
  404.     Int16        inWidthDelta,
  405.     Int16        inHeightDelta,
  406.     Boolean        inRefresh)
  407. {
  408.     if (inRefresh) {            // Refresh area covered before resize
  409.         Refresh();
  410.     }
  411.     
  412.     mFrameSize.width += inWidthDelta;
  413.     mFrameSize.height += inHeightDelta;
  414.     
  415.     if (inRefresh) {            // Refresh area covered after resize        
  416.         Refresh();    
  417.     }
  418.     
  419.         // +++ Figure out way to validate area that doesn't need to be
  420.         // refreshed. May need a flag. Some Panes do not depend on
  421.         // the frame for what they draw; others do.
  422. }
  423.  
  424.  
  425. // ---------------------------------------------------------------------------
  426. //        • MoveBy
  427. // ---------------------------------------------------------------------------
  428. //    Move the location of the Frame by the specified amounts
  429. //
  430. //        inHorizDelta and inVertDelta specify, in pixels, how far to move the
  431. //        Frame (within its surrounding Image). Positive horiz deltas move to
  432. //        the left, negative to the right. Positive vert deltas move down,
  433. //        negative up.
  434.  
  435. void
  436. LPane::MoveBy(
  437.     Int32        inHorizDelta,
  438.     Int32        inVertDelta,
  439.     Boolean        inRefresh)
  440. {
  441.     if (inRefresh) {
  442.         Refresh();
  443.     }
  444.     
  445.     mFrameLocation.h += inHorizDelta;
  446.     mFrameLocation.v += inVertDelta;
  447.     
  448.     if (inRefresh) {
  449.         Refresh();
  450.     }
  451. }
  452.  
  453.  
  454. // ---------------------------------------------------------------------------
  455. //        • PlaceInSuperFrameAt
  456. // ---------------------------------------------------------------------------
  457. //    Place the Pane at a location relative to the Frame of its SuperView
  458. //
  459. //        inHorizOffset specifies, in pixels, how far the left edge of the
  460. //        Frame is from the left edge of its Parent Frame. Positive offsets
  461. //        are to the left, negative to the right.
  462. //
  463. //        inVertOffset specifies, in pixels, how far the top edge of the
  464. //        Frame is from the top edge of its Parent Frame. Positive offsets
  465. //        are below, negative above.
  466.  
  467. void
  468. LPane::PlaceInSuperFrameAt(
  469.     Int32        inHorizOffset,
  470.     Int32        inVertOffset,
  471.     Boolean        inRefresh)
  472. {
  473.     SignalIf_(mSuperView == nil);
  474.     
  475.     SPoint32    superFrameLoc;        // Get location of SuperView's Frame
  476.     mSuperView->GetFrameLocation(superFrameLoc);
  477.     
  478.                                     // Move by difference between new
  479.                                     //   and current location
  480.     MoveBy(superFrameLoc.h + inHorizOffset - mFrameLocation.h,
  481.            superFrameLoc.v + inVertOffset - mFrameLocation.v,
  482.            inRefresh);
  483. }
  484.  
  485.  
  486. // ---------------------------------------------------------------------------
  487. //        • PlaceInSuperImageAt
  488. // ---------------------------------------------------------------------------
  489. //    Place the Pane within the Image of its SuperView
  490. //
  491. //    inHoriz and inVert specify the distance of the top left of the Frame
  492. //    from the top left of the Image of its SuperView
  493.  
  494. void
  495. LPane::PlaceInSuperImageAt(
  496.     Int32        inHorizOffset,
  497.     Int32        inVertOffset,
  498.     Boolean        inRefresh)
  499. {
  500.     SignalIf_(mSuperView == nil);
  501.     
  502.     SPoint32    superImageLoc;        // Get location of SuperView's Image
  503.     mSuperView->GetImageLocation(superImageLoc);
  504.     
  505.                                     // Move by difference between new
  506.                                     //   and current location
  507.     MoveBy(superImageLoc.h + inHorizOffset - mFrameLocation.h,
  508.            superImageLoc.v + inVertOffset - mFrameLocation.v,
  509.            inRefresh);
  510. }
  511.  
  512.  
  513. void
  514. LPane::SavePlace(
  515.     LStream        *outPlace)
  516. {
  517.     outPlace->WriteData(&mFrameSize, sizeof(SDimension16));
  518.     outPlace->WriteData(&mFrameLocation, sizeof(SPoint32));
  519. }
  520.  
  521.  
  522. void
  523. LPane::RestorePlace(
  524.     LStream        *inPlace)
  525. {
  526.     inPlace->ReadData(&mFrameSize, sizeof(SDimension16));
  527.     inPlace->ReadData(&mFrameLocation, sizeof(SPoint32));
  528. }
  529.  
  530.  
  531. // ---------------------------------------------------------------------------
  532. //        • PutInside
  533. // ---------------------------------------------------------------------------
  534. //    Put Pane inside the specified View. Location is unspecified.
  535.  
  536. void
  537. LPane::PutInside(
  538.     LView    *inView)
  539. {
  540.     if (mSuperView != nil) {            // Sever ties with old Parent
  541.         mSuperView->RemoveSubPane(this);
  542.     }
  543.     
  544.     mSuperView = inView;
  545.     
  546.     if (inView != nil) {                // Attach to new Parent
  547.         inView->AddSubPane(this);
  548.         AdaptToNewSurroundings();        // Adjust state to reflect new Parent
  549.     }
  550. }
  551.  
  552.  
  553. LView*
  554. LPane::GetSuperView()
  555. {
  556.     return mSuperView;
  557. }
  558.  
  559.  
  560. // ---------------------------------------------------------------------------
  561. //        • AdaptToNewSurroundings
  562. // ---------------------------------------------------------------------------
  563. //    Adjust state of Pane when installed in a new Parent Pane
  564.  
  565. void
  566. LPane::AdaptToNewSurroundings()
  567. {
  568. }
  569.  
  570.  
  571. // ---------------------------------------------------------------------------
  572. //        • AdaptToSuperFrameSize
  573. // ---------------------------------------------------------------------------
  574. //    Adjust state of Pane when size of SuperView's Frame changes by the
  575. //    specified amounts
  576.  
  577. void
  578. LPane::AdaptToSuperFrameSize(
  579.     Int32    inSurrWidthDelta,            // Change in width of SuperView
  580.     Int32    inSurrHeightDelta,            // Change in height of SuperView
  581.     Boolean    inRefresh)
  582. {
  583.         // When SuperView changes size, a Pane may move or change
  584.         // size, depending on how each of its sides is "bound" to
  585.         // that of its SuperView. A side that is bound always remains
  586.         // the same distance from the corresponding side of its SuperView.
  587.         
  588.     Int32        widthDelta = 0;
  589.     Int32        heightDelta = 0;
  590.     Int32        horizDelta = 0;
  591.     Int32        vertDelta = 0;
  592.  
  593.     if (mFrameBinding.right) {
  594.         if (mFrameBinding.left) {
  595.                                         // Both right and left are bound
  596.                                         // Pane resizes horizontally
  597.             widthDelta = inSurrWidthDelta;
  598.         } else {
  599.                                         // Right bound, left free
  600.                                         // Pane moves horizontally
  601.             horizDelta = inSurrWidthDelta;
  602.         }
  603.     }
  604.     
  605.     if (mFrameBinding.bottom) {
  606.         if (mFrameBinding.top) {
  607.                                         // Both bottom and top are bound
  608.                                         // Pane resizes vertically
  609.             heightDelta = inSurrHeightDelta;
  610.         } else {
  611.                                         // Bottom bound, left free
  612.                                         // Pane moves vertically
  613.             vertDelta = inSurrHeightDelta;
  614.         }
  615.     }
  616.     
  617.     if ( (widthDelta != 0) || (heightDelta != 0) ) {
  618.         ResizeFrameBy(widthDelta, heightDelta, inRefresh);
  619.     }
  620.     
  621.     if ( (horizDelta != 0) || (vertDelta != 0) ) {
  622.         MoveBy(horizDelta, vertDelta, inRefresh);
  623.     }
  624. }
  625.  
  626.  
  627. // ---------------------------------------------------------------------------
  628. //        • AdaptToSuperScroll
  629. // ---------------------------------------------------------------------------
  630. //    Adjust state of Pane when its SuperView scrolls by the specified amounts
  631.  
  632. void
  633. LPane::AdaptToSuperScroll(
  634.     Int32    inHorizScroll,
  635.     Int32    inVertScroll)
  636. {
  637.     Int32    horizDelta = 0;
  638.     Int32    vertDelta = 0;
  639.  
  640.     if (!mFrameBinding.left && !mFrameBinding.right) {
  641.                                         // Pane is not bound horizontally
  642.         horizDelta = -inHorizScroll;    // It moves along with the SuperImage
  643.     }
  644.     
  645.     if (!mFrameBinding.top && !mFrameBinding.bottom) {
  646.                                         // Pane is not bound vertically
  647.         vertDelta = -inVertScroll;        // It moves along with the SuperImage
  648.     }
  649.     
  650.     if ( (horizDelta != 0) || (vertDelta != 0) ) {
  651.         MoveBy(horizDelta, vertDelta, false);
  652.     }
  653. }
  654.  
  655.  
  656. // ===========================================================================
  657. // • Mouse Clicks                                                Mouse Clicks •
  658. // ===========================================================================
  659.  
  660. // ---------------------------------------------------------------------------
  661. //        • PointIsInFrame
  662. // ---------------------------------------------------------------------------
  663. //    Return whether a Point is inside the Frame of a Pane
  664. //
  665. //    inHorizPort and inVertPort are in Port coordinates
  666.  
  667. Boolean
  668. LPane::PointIsInFrame(
  669.     Int32    inHorizPort,
  670.     Int32    inVertPort) const
  671. {
  672.     return ( (inHorizPort >= mFrameLocation.h)  &&
  673.              (inHorizPort <= mFrameLocation.h + mFrameSize.width)  &&
  674.              (inVertPort >= mFrameLocation.v)  &&
  675.              (inVertPort <= mFrameLocation.v + mFrameSize.height) );
  676. }
  677.  
  678.  
  679. // ---------------------------------------------------------------------------
  680. //        • IsHitBy
  681. // ---------------------------------------------------------------------------
  682. //    Return whether a Pane is hit by the specified point, which is in
  683. //    Port coordinates
  684. //
  685. //    A Pane is hit if the point is inside its Frame and the Pane is enabled
  686.  
  687. Boolean
  688. LPane::IsHitBy(
  689.     Int32    inHorizPort,
  690.     Int32    inVertPort)
  691. {
  692.     return (PointIsInFrame(inHorizPort, inVertPort) && IsEnabled());
  693. }
  694.  
  695.  
  696. // ---------------------------------------------------------------------------
  697. //        • FindSubPaneHitBy
  698. // ---------------------------------------------------------------------------
  699. //    Find the SubPane of this Pane that is hit by the specified point.
  700. //    Return nil if no SubPane is hit
  701. //
  702. //    inHorizPort and inVertPort are in Port coordinates
  703.  
  704. LPane*
  705. LPane::FindSubPaneHitBy(
  706.     Int32    inHorizPort,
  707.     Int32    inVertPort)
  708. {
  709.     return nil;                    // A Pane has no SubPanes
  710. }
  711.  
  712.  
  713. LPane*
  714. LPane::GetLastPaneClicked()
  715. {
  716.     return sLastPaneClicked;
  717. }
  718.  
  719.  
  720. Int16
  721. LPane::GetClickCount()
  722. {
  723.     return sClickCount;
  724. }
  725.  
  726.  
  727. // ---------------------------------------------------------------------------
  728. //        • Click
  729. // ---------------------------------------------------------------------------
  730. //    Handle a click inside a Pane
  731.  
  732. void
  733. LPane::Click(
  734.     SMouseDownEvent    &inMouseDown)
  735. {
  736.     if (!inMouseDown.delaySelect) {
  737.         PortToLocalPoint(inMouseDown.whereLocal);
  738.         UpdateClickCount(inMouseDown);
  739.         ClickSelf(inMouseDown);
  740.     }
  741. }
  742.  
  743.  
  744. // ---------------------------------------------------------------------------
  745. //        • ClickSelf
  746. // ---------------------------------------------------------------------------
  747. //    Respond to Click inside this Pane
  748.  
  749. void
  750. LPane::ClickSelf(
  751.     const SMouseDownEvent    &inMouseDown)
  752. {
  753. }
  754.  
  755.  
  756. // ---------------------------------------------------------------------------
  757. //        • EventMouseUp
  758. // ---------------------------------------------------------------------------
  759. //    Respond to a mouse up event following a click (mouse down) inside a Pane
  760.  
  761. void
  762. LPane::EventMouseUp(
  763.     const EventRecord    &inMouseUp)
  764. {
  765.     sWhenLastMouseUp = inMouseUp.when;    // Needed for multi-click detection
  766. }
  767.  
  768.  
  769. // ---------------------------------------------------------------------------
  770. //        • UpdateClickCount
  771. // ---------------------------------------------------------------------------
  772. //    Determine if the mouse down is part of a multi-click and set internal
  773. //    counters
  774.  
  775. void
  776. LPane::UpdateClickCount(
  777.     const SMouseDownEvent    &inMouseDown)
  778. {
  779.         // Three conditions necessary for a multi-click:
  780.         //   1) This is the same Pane as was hit with the last mouse down
  781.         //   2) Times of previous and current clicks are close enough
  782.         //   3) Locations of previous and current clicks are close enough
  783.         
  784.     if ( (sLastPaneClicked == this) &&
  785.          ClickTimesAreClose(inMouseDown.macEvent.when) &&
  786.          PointsAreClose(sWhereLastMouseDown, inMouseDown.whereLocal) ) {
  787.              
  788.              sClickCount++;
  789.  
  790.     } else {
  791.         sClickCount = 1;
  792.     }
  793.  
  794.                                     // Save info about this click
  795.     sLastPaneClicked = this;
  796.     sWhereLastMouseDown = inMouseDown.whereLocal;
  797.     sWhenLastMouseDown = inMouseDown.macEvent.when;
  798. }
  799.  
  800.  
  801. // ---------------------------------------------------------------------------
  802. //        • PointsAreClose
  803. // ---------------------------------------------------------------------------
  804. //    Return whether the two points are close enough to be part of a
  805. //    multi-click. Points are in Local coordinates.
  806.  
  807. Boolean
  808. LPane::PointsAreClose(
  809.     Point    inFirstPt,
  810.     Point    inSecondPt)
  811. {
  812.     Int16    hDelta = inFirstPt.h - inSecondPt.h;
  813.     if (hDelta < 0) {
  814.         hDelta = -hDelta;
  815.     }
  816.     Int16    vDelta = inFirstPt.v - inSecondPt.v;
  817.     if (vDelta < 0) {
  818.         vDelta = -vDelta;
  819.     }
  820.     
  821.     return ( (hDelta <= multiClick_Distance) &&
  822.              (vDelta <= multiClick_Distance) );
  823. }
  824.  
  825.  
  826. Boolean
  827. LPane::ClickTimesAreClose(
  828.     Uint32    inLastClickTime)
  829. {
  830.     return ((inLastClickTime - sWhenLastMouseDown) <= GetDblTime());
  831. }
  832.  
  833.  
  834. void
  835. LPane::AdjustCursor(
  836.     Point                inPortPt,
  837.     const EventRecord    &inMacEvent)
  838. {
  839.     AdjustCursorSelf(inPortPt, inMacEvent);
  840. }
  841.  
  842.  
  843. // ---------------------------------------------------------------------------
  844. //        • AdjustCursorSelf
  845. // ---------------------------------------------------------------------------
  846. //    Set the cursor shape when the cursor is inside a Pane
  847. //
  848. //    The input point is in Port coordinates. Use the inMacEvent->modifiers
  849. //    if the cursor shape depends on whether modifier keys (such as Option)
  850. //    are down.
  851.  
  852. void
  853. LPane::AdjustCursorSelf(
  854.     Point                inPortPt,
  855.     const EventRecord    &inMacEvent)
  856. {
  857.     SetCursor(&qd.arrow);
  858. }
  859.  
  860.  
  861. Boolean
  862. LPane::IsVisible() const
  863. {
  864.     return (mVisible == triState_On);
  865. }
  866.  
  867.  
  868. void
  869. LPane::Show()
  870. {
  871.     if (mVisible == triState_Off) {
  872.         if ((mSuperView != nil) && mSuperView->IsVisible()) {
  873.             mVisible = triState_On;
  874.             ShowSelf();
  875.         } else {
  876.             mVisible = triState_Latent;
  877.         }
  878.     }
  879. }
  880.  
  881.  
  882. void
  883. LPane::SuperShow()
  884. {
  885.     if (mVisible == triState_Latent) {
  886.         mVisible = triState_On;
  887.         ShowSelf();
  888.     }
  889. }
  890.  
  891.  
  892. void
  893. LPane::ShowSelf()
  894. {
  895.     Refresh();
  896. }
  897.  
  898.  
  899. void
  900. LPane::Hide()
  901. {
  902.     Boolean        wasVisible = IsVisible();
  903.     mVisible = triState_Off;
  904.     if (wasVisible) {
  905.         HideSelf();
  906.     }
  907. }
  908.  
  909.  
  910. void
  911. LPane::SuperHide()
  912. {
  913.     if (mVisible == triState_On) {
  914.         mVisible = triState_Latent;
  915.         HideSelf();
  916.     }
  917. }
  918.  
  919.  
  920. void
  921. LPane::HideSelf()
  922. {
  923.     Rect    frame;                    // Force redraw of area covered by Pane
  924.     if (CalcPortFrameRect(frame)) {    // Don't call Refresh(), which works
  925.         InvalPortRect(&frame);        //   only if Pane is visible.
  926.     }
  927. }
  928.  
  929.  
  930. Boolean
  931. LPane::IsActive() const
  932. {
  933.     return ((mActive == triState_On) && IsVisible());
  934. }
  935.  
  936.  
  937. void
  938. LPane::Activate()
  939. {
  940.     if (mActive == triState_Off) {
  941.         if ((mSuperView != nil) && mSuperView->IsActive()) {
  942.             mActive = triState_On;
  943.             if (IsActive()) {
  944.                 ActivateSelf();
  945.             }
  946.         } else {
  947.             mActive = triState_Latent;
  948.         }
  949.     }
  950. }
  951.  
  952.  
  953. void
  954. LPane::SuperActivate()
  955. {
  956.     if (mActive == triState_Latent) {
  957.         mActive = triState_On;
  958.         if (IsActive()) {
  959.             ActivateSelf();
  960.         }
  961.     }
  962. }
  963.  
  964.  
  965. void
  966. LPane::ActivateSelf()
  967. {
  968. }
  969.  
  970.  
  971. void
  972. LPane::Deactivate()
  973. {
  974.     Boolean        wasActive = IsActive();
  975.     
  976.     mActive = triState_Off;
  977.     if (wasActive) {
  978.         DeactivateSelf();
  979.     }
  980. }
  981.  
  982.  
  983. void
  984. LPane::SuperDeactivate()
  985. {
  986.     if (mActive == triState_On) {
  987.         Boolean        wasActive = IsActive();
  988.         mActive = triState_Latent;
  989.         if (wasActive) {
  990.             DeactivateSelf();
  991.         }
  992.     }
  993. }
  994.  
  995.  
  996. void
  997. LPane::DeactivateSelf()
  998. {
  999. }
  1000.  
  1001.  
  1002. Boolean
  1003. LPane::IsEnabled() const
  1004. {
  1005.     return ((mEnabled == triState_On) && IsVisible());
  1006. }
  1007.  
  1008.  
  1009. // ---------------------------------------------------------------------------
  1010. //        • Enable
  1011. // ---------------------------------------------------------------------------
  1012. //    Enable a Pane
  1013.  
  1014. void
  1015. LPane::Enable()
  1016. {
  1017.     if (mEnabled == triState_Off) {
  1018.         if ((mSuperView != nil) && mSuperView->IsEnabled()) {
  1019.             mEnabled = triState_On;
  1020.             if (IsEnabled()) {
  1021.                 EnableSelf();
  1022.             }
  1023.         } else {
  1024.             mEnabled = triState_Latent;
  1025.         }
  1026.     }
  1027. }
  1028.  
  1029.  
  1030. void
  1031. LPane::SuperEnable()
  1032. {
  1033.     if (mEnabled == triState_Latent) {
  1034.         mEnabled = triState_On;
  1035.         if (IsEnabled()) {
  1036.             EnableSelf();
  1037.         }
  1038.     }
  1039. }
  1040.  
  1041.  
  1042. void
  1043. LPane::EnableSelf()
  1044. {
  1045. }
  1046.  
  1047.  
  1048. // ---------------------------------------------------------------------------
  1049. //        • Disable
  1050. // ---------------------------------------------------------------------------
  1051. //    Disable a Pane
  1052.  
  1053. void
  1054. LPane::Disable()
  1055. {
  1056.     Boolean        wasEnabled = IsEnabled();
  1057.     
  1058.     mEnabled = triState_Off;
  1059.     if (wasEnabled) {
  1060.         DisableSelf();
  1061.     }
  1062. }
  1063.  
  1064.  
  1065. void
  1066. LPane::SuperDisable()
  1067. {
  1068.     if (mEnabled == triState_On) {
  1069.         Boolean        wasEnabled = IsEnabled();
  1070.         mEnabled = triState_Latent;
  1071.         if (wasEnabled) {
  1072.             DisableSelf();
  1073.         }
  1074.     }
  1075. }
  1076.  
  1077.  
  1078. void
  1079. LPane::DisableSelf()
  1080. {
  1081. }
  1082.  
  1083.  
  1084. void
  1085. LPane::LockDrawing()
  1086. {
  1087.     mLockLevel--;
  1088. }
  1089.  
  1090.  
  1091. void
  1092. LPane::UnlockDrawing()
  1093. {
  1094.     mLockLevel++;
  1095. }
  1096.  
  1097.  
  1098. void
  1099. LPane::Refresh()
  1100. {
  1101.     Rect    frame;
  1102.     if (IsVisible() && CalcPortFrameRect(frame)) {
  1103.         InvalPortRect(&frame);
  1104.     }
  1105. }
  1106.  
  1107.  
  1108. // ===========================================================================
  1109. // • Invalidate/Validate                                 Invalidate/Validate •
  1110. // ===========================================================================
  1111. //    All rectangles and regions must be in Port coordinates
  1112. //
  1113. //    You should use these routines rather than the Toolbox traps InvalRect,
  1114. //    InvalRgn, ValidRect, and ValidRgn. Those traps require that the current
  1115. //    GrafPort be a Window. However, a Pane could be in another kind of
  1116. //    GrafPort, such as a Printer Port or GWorld, where calling one of those
  1117. //    traps would cause a horrible crash (when the Toolbox tries to access
  1118. //    a nonexistant update region).
  1119.  
  1120. void
  1121. LPane::InvalPortRect(
  1122.     const Rect    *inRect)
  1123. {
  1124.     if (mSuperView != nil) {
  1125.         mSuperView->InvalPortRect(inRect);
  1126.     }
  1127. }
  1128.  
  1129.  
  1130. void
  1131. LPane::InvalPortRgn(
  1132.     RgnHandle    inRgnH)
  1133. {
  1134.     if (mSuperView != nil) {
  1135.         mSuperView->InvalPortRgn(inRgnH);
  1136.     }
  1137. }
  1138.  
  1139.  
  1140. void
  1141. LPane::ValidPortRect(
  1142.     const Rect    *inRect)
  1143. {
  1144.     if (mSuperView != nil) {
  1145.         mSuperView->ValidPortRect(inRect);
  1146.     }
  1147. }
  1148.  
  1149.  
  1150. void
  1151. LPane::ValidPortRgn(
  1152.     RgnHandle    inRgnH)
  1153. {
  1154.     if (mSuperView != nil) {
  1155.         mSuperView->ValidPortRgn(inRgnH);
  1156.     }
  1157. }
  1158.  
  1159.  
  1160. // ---------------------------------------------------------------------------
  1161. //        • UpdatePort
  1162. // ---------------------------------------------------------------------------
  1163. //    Redraw invalidated area of the Port containing the Pane
  1164. //
  1165. //        For Panes that are in a Window Port (i.e., the ultimate super view
  1166. //        is a Window), this forces an immediate redraw of the update region
  1167. //        of the Window. Since this message is really directed at the Port
  1168. //        containing the Pane (rather than the Pane itself), the update occurs
  1169. //        even if the Pane is not visible.
  1170. //
  1171. //        Panes that maintain a Mac GrafPort must override this function if
  1172. //        they support updating.
  1173.  
  1174. void
  1175. LPane::UpdatePort()
  1176. {
  1177.     if (mSuperView != nil) {
  1178.         mSuperView->UpdatePort();
  1179.     }
  1180. }
  1181.  
  1182.  
  1183. // ---------------------------------------------------------------------------
  1184. //        • FocusDraw
  1185. // ---------------------------------------------------------------------------
  1186. //    Prepare for drawing in the Pane
  1187. //
  1188. //    Returns true if the Pane is focused
  1189. //    Returns false if the Pane could not be focused
  1190. //
  1191. //    A Pane does not have its own coordinate system and clipping region.
  1192. //    It relies on its SuperView to set the focus.
  1193.  
  1194. Boolean
  1195. LPane::FocusDraw()
  1196. {
  1197.     return  ( (mLockLevel >= 0)  &&
  1198.               ((mSuperView == nil)  ||  mSuperView->FocusDraw()) );
  1199. }
  1200.  
  1201.  
  1202. // ---------------------------------------------------------------------------
  1203. //        • Draw
  1204. // ---------------------------------------------------------------------------
  1205. //    Try to draw contents of a Pane
  1206. //
  1207. //    inSuperDrawRgnH specifies, in Port coordinates, the portion of the
  1208. //    Pane's SuperView that needs to be drawn. Specify nil to bypass
  1209. //    the intersection test.
  1210. //    
  1211. //    This is a wrapper function which calls DrawSelf if it is proper for
  1212. //    the Pane to draw. This means that:
  1213. //        > Pane's Visible property is on
  1214. //        > Pane can be focused
  1215. //        > Pane's Frame is in QuickDraw space
  1216. //        > Pane's Frame intersects inSuperDrawRgnH
  1217.  
  1218. void
  1219. LPane::Draw(
  1220.     RgnHandle    inSuperDrawRgnH)
  1221. {
  1222.     Rect    frame;
  1223.     if ( IsVisible()  &&
  1224.          FocusDraw()  &&
  1225.          CalcPortFrameRect(frame)  &&
  1226.          ((inSuperDrawRgnH == nil) || RectInRgn(&frame, inSuperDrawRgnH)) ) {
  1227.         DrawSelf();
  1228.     }
  1229. }
  1230.  
  1231.  
  1232. // ---------------------------------------------------------------------------
  1233. //        • DrawSelf
  1234. // ---------------------------------------------------------------------------
  1235. //    Draw contents of Pane
  1236. //
  1237. //    Derived classes must override this function in order to draw. Normally,
  1238. //    you will call CalcLocalFrameRect to get a QuickDraw rectangle defining
  1239. //    the size and location of the Pane. Perform all drawing operations
  1240. //    relative to the frame rectangle. For example:
  1241. //
  1242. //        PenNormal();
  1243. //        Rect    frame;
  1244. //        CalcLocalFrameRect(frame);
  1245. //        FrameRect(&frame);
  1246. //        MoveTo(frame.left, frame.top);
  1247. //        LineTo(frame.right, frame.bottom);
  1248. //
  1249. //            This draws a box around the Pane and a diagonal line from
  1250. //            the top left to the bottom right corner.
  1251. //
  1252. //    Clipping:
  1253. //    On entry, the clipping region is the revealed area of the Pane's
  1254. //    SuperView. Therefore, it is possible for a Pane to draw outside of
  1255. //    its Frame. You will not normally do this.
  1256. //
  1257. //    Usage Note: The port, coordinate system, and clipping region are
  1258. //        set on entry. They must be the same upon exit. You are responsible
  1259. //        for setting the Pen state and text characteristics to the proper
  1260. //        values for your Pane.
  1261.  
  1262. void
  1263. LPane::DrawSelf()
  1264. {
  1265. }
  1266.  
  1267.  
  1268. // ---------------------------------------------------------------------------
  1269. //        • CountPanels
  1270. // ---------------------------------------------------------------------------
  1271. //    Return the number of horizontal and vertical Panels. A Panel is a
  1272. //    "frameful" of a Pane.
  1273.  
  1274. void
  1275. LPane::CountPanels(
  1276.     Uint32    &outHorizPanels,
  1277.     Uint32    &outVertPanels)
  1278. {
  1279.     outHorizPanels = 1;                    // A Pane is the same size as its
  1280.     outVertPanels = 1;                    //   Frame, so there's only one Panel
  1281. }
  1282.  
  1283.  
  1284. // ---------------------------------------------------------------------------
  1285. //        • PrintPanel
  1286. // ---------------------------------------------------------------------------
  1287. //    Try to Print a Panel of a Pane
  1288.  
  1289. void
  1290. LPane::PrintPanel(
  1291.     const PanelSpec    &inPanel,
  1292.     RgnHandle        inSuperPrintRgnH)
  1293. {
  1294.     Rect    frame;
  1295.     if ( IsVisible()  &&
  1296.          FocusDraw()  &&
  1297.          CalcPortFrameRect(frame)  &&
  1298.          ((inSuperPrintRgnH == nil) ||
  1299.              RectInRgn(&frame, inSuperPrintRgnH)) ) {
  1300.         PrintPanelSelf(inPanel);
  1301.     }
  1302. }
  1303.  
  1304.  
  1305. // ---------------------------------------------------------------------------
  1306. //        • SuperPrintPanel
  1307. // ---------------------------------------------------------------------------
  1308. //    SuperView is printing a panel
  1309.  
  1310. void
  1311. LPane::SuperPrintPanel(
  1312.     const PanelSpec    &inSuperPanel,
  1313.     RgnHandle        inSuperPrintRgnH)
  1314. {
  1315.     PrintPanel(inSuperPanel, inSuperPrintRgnH);
  1316. }
  1317.  
  1318.  
  1319. // ---------------------------------------------------------------------------
  1320. //        • PrintPanelSelf
  1321. // ---------------------------------------------------------------------------
  1322. //    Print a Panel of a Pane
  1323.  
  1324. void
  1325. LPane::PrintPanelSelf(
  1326.     const PanelSpec    &inPanel)
  1327. {
  1328.     DrawSelf();
  1329. }
  1330.  
  1331.  
  1332. // ---------------------------------------------------------------------------
  1333. //        • PortToLocalPoint
  1334. // ---------------------------------------------------------------------------
  1335. //    Convert point from Port to Local coordinates
  1336.  
  1337. void
  1338. LPane::PortToLocalPoint(
  1339.     Point    &ioPoint) const
  1340. {
  1341.     if (mSuperView != nil) {
  1342.         mSuperView->PortToLocalPoint(ioPoint);
  1343.     }
  1344. }
  1345.  
  1346.  
  1347. // ---------------------------------------------------------------------------
  1348. //        • LocalToPortPoint
  1349. // ---------------------------------------------------------------------------
  1350. //    Convert point from Local to Port coordinates
  1351.  
  1352. void
  1353. LPane::LocalToPortPoint(
  1354.     Point    &ioPoint) const
  1355. {
  1356.     if (mSuperView != nil) {
  1357.         mSuperView->LocalToPortPoint(ioPoint);
  1358.     }
  1359. }
  1360.  
  1361.  
  1362. void
  1363. LPane::GlobalToPortPoint(
  1364.     Point    &ioPoint) const
  1365. {
  1366.     if (mSuperView != nil) {
  1367.         mSuperView->GlobalToPortPoint(ioPoint);
  1368.     }
  1369. }
  1370.  
  1371.  
  1372. void
  1373. LPane::PortToGlobalPoint(
  1374.     Point    &ioPoint) const
  1375. {
  1376.     if (mSuperView != nil) {
  1377.         mSuperView->PortToGlobalPoint(ioPoint);
  1378.     }
  1379. }